﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.IO;
using NLBS.Utility;
using System.Reflection;

namespace NLBS.WebControls.UI
{
    [ToolboxItem(false)]
    [DefaultProperty("Text")]
    [ToolboxData("<{0}:CallBack runat=server></{0}:CallBack>")]
    [Designer(typeof(NLBS.WebControls.UI.CallbackDesigner))]
    public class CallBack : WebControl
    {
        #region event
        /// <summary>
        /// this event for callback
        /// </summary>
        public event CallBackEventHanlder Callback;

        protected void OnCallback(CallBackEventArgs e)
        {
            if (Callback != null)
            {
                Callback(this, e);
            }
        }
        #endregion


        #region property

        private List<object> _callBackMethodCollection;
        public List<object> CallBackMethodCollection
        {
            get
            {
                if (_callBackMethodCollection == null)
                {
                    _callBackMethodCollection = new List<object>();
                }
                return _callBackMethodCollection;
            }
        }

        private string _parameter;
        public string Parameter
        {
            get { return _parameter != null ? _parameter : string.Empty; }
            set { _parameter = value; }
        }
        [ClientSerializable("ddd")]
        public int  Interval { get; set; }
        public bool LoadProtoTypeJS { get; set; }
        [ClientSerializable("ExtendClientID")]
        public string ExtendClientID { get; set; }
       
        #endregion

        #region method



        public string[] GetCallbackParameters()
        {
            string sCallbackParamVar = string.Format("{0}_Param", this.ExtendClientID);
            string[] arParams = null;

            if (Context != null)
            {
                arParams = Context.Request.Form.GetValues(sCallbackParamVar);
                if(arParams==null)
                arParams = Context.Request.QueryString.GetValues(sCallbackParamVar);
            }

            return arParams;
        }

        private string GetClientID()
        {
            if (ExtendClientID == null)
            {
                ExtendClientID = this.ClientID;
            }
            return ExtendClientID;
        }

        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        [PersistenceMode(PersistenceMode.InnerProperty)]
        public PlaceHolder CallBackContent { get; set; }

        public bool EnablePanel { get; set; }

        private void HandleCallback(string[] arParams)
        {
            try
            {
                //try render the HtmlTextWriter
                
                StringWriter oStringWriter = new StringWriter();
                HtmlTextWriter oWriter = new HtmlTextWriter(oStringWriter, string.Empty);

                CallBackEventArgs oArgs = new CallBackEventArgs(oWriter);
                oArgs.Parameter = arParams[0];
                oArgs.Parameters = arParams;

                this.OnCallback(oArgs);
                HandleCallbackMethod();
                oWriter.Close();

                Context.Response.Clear();
                
                Context.Response.Write(oStringWriter.ToString().Trim());
                //Context.Response.ContentType = "text/xml";
                //Context.Response.Write("<CallbackContent><![CDATA[");
               // Context.Response.Write(oStringWriter.ToString().Replace("]]>", "$$$CART_CDATA_CLOSE$$$"));
               // Context.Response.Write("]]></CallbackContent>");
            }
            catch (Exception ex)
            {
                this.HandleCallbackError(ex);
            }

            try
            {
                Context.Response.End();
            }
            catch 
            {
               
            }

        }

        private void HandleCallbackError(Exception ex)
        {
            // don't output child tables
            Context.Response.Clear();
            Context.Response.ContentType = "text/xml";
            Context.Response.Write("<CallbackError><![CDATA[");
            Context.Response.Write(ex.Message);
            Context.Response.Write("]]></CallbackError>");
            Context.Response.End();
        }

        #endregion

        //protected override void RenderContents(HtmlTextWriter output)
        //{
        //    string[] requestParams = this.GetCallbackParameters();
        //    // if this is a callback request
        //    if (requestParams != null && requestParams.Length > 0)
        //    {
        //        this.HandleCallback(requestParams);
        //        return;
        //    }
        //}

        private void HandleCallbackMethod()
        {
            if (this.CallBackMethodCollection != null && this.CallBackMethodCollection.Count > 0)
            {
                CallMethod = new Dictionary<string, MethodInfo>();
                foreach (object itemMethod in CallBackMethodCollection)
                {
                    foreach (MethodInfo itemInfo in itemMethod.GetType().GetMethods())
                    {
                        object[] attributes = itemInfo.GetCustomAttributes(typeof(CallBackMethodAttribute), false);
                        if (attributes.Length > 0)
                        {
                            foreach (object obj in attributes)
                            {
                                CallBackMethodAttribute ca = (CallBackMethodAttribute)obj;
                                if (ca.CallName == this.GetCallbackParameters()[0])
                                {
                                    itemInfo.Invoke(itemMethod, null);
                                    return;
                                }
                            }
                        }
                    }
                }
            }
        }
        //8613
        public Dictionary<string, MethodInfo> CallMethod;

        protected override void Render(HtmlTextWriter writer)
        {
            //得到一个querystring参数
            string[] requestParams = this.GetCallbackParameters();
            
            if (requestParams != null && requestParams.Length > 0)
            {
                //输出控件数据
                this.HandleCallback(requestParams);
                
                return;
            }
           // GZipHelper.GZipEncodePage();
            base.Render(writer);
        }
        // if this is a callback request
        //writer.Write(string.Format("<div id=\"{0}\"></div>",this.GetClientID()));
        // writer.Write(string.Format("<script>{0}</script>", this.RenderClientObject()));
        private string RenderClientObject()
        {
            return string.Empty;
            //string clientID = this.GetClientID();
            //StringBuilder clientjs = new StringBuilder();
            //string clientObject = ClientObjectSerializer.Serialize(typeof(CallBack), this);
            //return string.Format("var {0}=new nlbs_Callback(\"{0}\",{1});", clientID, clientObject);
        }

        protected override void OnPreRender(EventArgs e)
        {
            //if (LoadProtoTypeJS)
            //{
            //    if (!this.Page.ClientScript.IsClientScriptIncludeRegistered("prototype"))
            //    {
            //        this.Page.ClientScript.RegisterClientScriptInclude("prototype", "/Common/Script/protoaculous1.6.packed.js");
            //    }
            //}
            //if (!this.Page.ClientScript.IsClientScriptIncludeRegistered("nlbscallback"))
            //{
            //    this.Page.ClientScript.RegisterClientScriptInclude("nlbscallback", "/NlbsControl/NLBSCallBack.js");
            //}
           // this.Page.ClientScript.RegisterStartupScript(this.GetType(), this.ClientID + "key", RenderClientObject(), true);
            base.OnPreRender(e);
        }

        protected override void CreateChildControls()
        {
            this.Controls.Clear();
            if (EnablePanel)
            {
                if (CallBackContent != null)
                {
                    this.Controls.Add(CallBackContent);
                }
            }
            base.CreateChildControls();
            
        }
    }
    

}
